﻿using System;
using System.Collections.Generic;
 
using System.Text;
using System.IO;
using GGSharp.Packets;

namespace GGSharp.Structures
{
    public abstract class StuctureBase
    {
        protected const uint UINFLAG_AUDIO7 = 0x20000000;
        protected const uint UINFLAG_AUDIO = 0x40000000;
        protected const uint UINFLAG_ERA_OMNIX = 0x08000000;

        private int _length = 0;
        private int? _readedLength;

        public StuctureBase() { }
        public StuctureBase(BinaryReader reader) { Read(reader); }

        public virtual int Length
        {
            get { return _length; }
            protected set { _length = value; }
        }

        public int? ReadedLength
        {
            get { return _readedLength; }
            protected set { _readedLength = value; }
        }

        public abstract void Read(BinaryReader reader);
        public abstract void Write(BinaryWriter writer);

        protected int GetTimeFromDescription(byte[] bytes, int descriptionLength)
        {
            if (descriptionLength >= bytes.Length)
                return 0;

            int timeLength = bytes.Length - descriptionLength;
            if (timeLength == 4)
                return BitConverter.ToInt32(bytes, descriptionLength);
            else if (timeLength == 5)
                return BitConverter.ToInt32(bytes, descriptionLength + 1);

            return 0;
        }

        protected string ReadCP1250Text(BinaryReader reader)
        {
            List<byte> buffer = new List<byte>();
            byte c;

            do
            {
                c = reader.ReadByte();
                if (c != 0)
                    buffer.Add(c);
            }
            while (c != 0);

            return ReadCP1250Text(buffer.ToArray(), 0, buffer.Count);
        }

        protected string ReadCP1250Text(byte[] bytes)
        {
            return ReadCP1250Text(bytes, 0);
        }

        protected string ReadCP1250Text(byte[] bytes, int startIndex)
        {
            if (bytes.Length == startIndex)
                return "";

            int i = startIndex;
            byte c = 0;
            do
            {
                c = bytes[i++];
            }
            while (c != 0 && i < bytes.Length);

            if (i == bytes.Length)
                i++;

            return ReadCP1250Text(bytes, startIndex, i - 1 - startIndex);
        }

        protected string ReadCP1250Text(byte[] bytes, int startIndex, int readCount)
        {
            return Encoding.GetEncoding("windows-1250").GetString(bytes, startIndex, readCount);
        }

        protected string ReadUTF8Text(BinaryReader reader, int readCount)
        {
            return Encoding.UTF8.GetString(reader.ReadBytes(readCount));
        }

        protected GGShowType TranslateShow(int show)
        {
            try
            {
                return (GGShowType)show;
            }
            catch (Exception e)
            {
                return GGShowType.Unknown;
            }
        }

        protected ClientVersion TranslateClientVersion(int version)
        {
            try
            {
                return (ClientVersion)version;
            }
            catch (Exception e)
            {
                return ClientVersion.Unknown;
            }
        }

        protected void WriteCP1250Text(string text, BinaryWriter writer)
        {
            writer.Write(Encoding.GetEncoding("windows-1250").GetBytes(text));
            writer.Write('\0');
        }

        protected bool HasDescription(GGShowType show)
        {
            if (show == GGShowType.AvailableDescription || show == GGShowType.BusyDescription
                || show == GGShowType.InvisibleDescription || show == GGShowType.NotAvailableDescription)
                return true;
            else
                return false;
        }
    }
}
